#ifndef __NETWORK_H__
#define __NETWORK_H__

#include <vector>
#include "actor.h"
#include "newtypes.h"

#include <iostream>                  // for std::cout
#include <utility>                   // for std::pair
#include <algorithm>                 // for std::for_each
using namespace std;

#include <boost/graph/adjacency_list.hpp>
#include <boost/unordered_map.hpp>
using namespace boost;

//typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;
typedef adjacency_list < listS, vecS,
		undirectedS, no_property, property < edge_weight_t, double > > Graph;

typedef boost::unordered_map<int, vector<int>*> unorderedMap;

//typedef adjacency_list < setS, setS,
//		undirectedS, no_property, property < edge_weight_t, double, property<edge_weight2_t, double> > >  Graph2;


class Actor;
// TODO: Name it Network or Graph?
// TODO: src, dest - are they zero-based or 1-based?
class Network
{
// Data
public:
    // Data structure. Pls. modify appropriately. Pls. make sure that memory
    // is allocated and de-allocated appropriately.
    // int** adjMatrix;
private:
    Graph *g;
    // - not needed now as Srinath and Subbu decided
    //vector<Actor*> actorList;
    unorderedMap* distanceMap;
    bool* staleInformation;

// Methods
public:
    Network();

    Network(int numOfVertices, double density);

    // copy constructor.
    Network(const Network& ntwk);

    ~Network();

    // Initialializes the network object - not needed now
    //   (1) setup the initial edges (randomly) from density parameter
    //   (2) Create the actors and store a ptr to each actor in vecActors
    // void init();


    // Return the number of edges on the geodesic (shortest path) between
    // srcNode and destNode
    int getNumEdgesOnGeodesic( int srcNode, int destNode ) const;

    // classify and return the network structure
    // uses: (1) sorted in-out degree vector
    //       (2) total mean squared deviation (structural fit metric)
    NTWK_STRUCT getNetworkStructure(ofstream *ofile);


    // adds an edge between 'src' and 'dest' nodes
    void add( int src, int dest );

    // deletes/removes the edge between 'src' and 'dest' nodes
    // NOTE: 'delete' is a keyword in C++. So, could not use that for method name.
    void remove( int src, int dest );


    // TODO: Discuss whether the adjecency matrix should be accessible outside this class
    // Good programming means that we should not have access to this matrix.

    // If the network data structure is exposed to outside world, then the following method may not be required.
    // Returns true if 'dest' is adjacent to 'dest'. Returns false otherwise.
    bool isAdjacent( int src, int dest );


    // Dumps the current state of the network to the specified file.
    // Uses append mode.
    // TODO: Header to identify the start of a new dump (Rohith and Greg to decide)
    void dumpNetwork( const char* fileName );

    // returns the sum of all utilities of actors in the network - not needed now as Srinath and Subbu decided
    // double getUtility();

    // returns the actors in the network - not needed now as Srinath and Subbu decided
    //const vector<Actor*>& getActors() const;

    // returns a ref to boost graph object
    const Graph& getGraph() const;

    const bool* getStaleInformationList()const;
    const unorderedMap* getUnorderedMap()const;
private:
	Network operator = (const Network &);

protected:
};


#endif
